// Ninf-G-XX, ver. 0.1
// Copyright 2011 National Institute of Advanced Industrial Science and Technology
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string>
#include <cstring>
#include <unistd.h>
#include "Global.hpp"
#include "Submit.hpp"
#include "CondorSubmit.hpp"
#include "Exception.hpp"

using namespace ninf::client;
Submit :: Submit(const char * module, const char * entry, int id)
		:module(strdup(module)), entry(strdup(entry))
		, id(id), linkCounter(0)
{
  char buffer[1000];
  sprintf(buffer, "%s/" TO_FF,   Global::global.runDir, id);
  toPrefix =   strdup(buffer);
  sprintf(buffer, "%s/" FROM_FF,   Global::global.runDir, id);
  fromPrefix = strdup(buffer);
  sprintf(buffer, "%s/" META_FF,   Global::global.runDir, id);
  metaPrefix = strdup(buffer);

  sprintf(buffer, TO_FF,   id);
  relativeTo =   strdup(buffer);
  sprintf(buffer, FROM_FF, id);
  relativeFrom = strdup(buffer);
}

Submit :: ~Submit(){
	free((char *)module);
	free((char *)entry);

}

/**
 *  create symbolic links from condor working directory
 *  so that it will be easily transfered out and in
 */
const char *
Submit :: makeSymLink(const char * filename){
  char newShort[100];
  char newFilename[1000];
  char oldFilename[1000];

  sprintf(newShort, "link%d_%d",
	  id, linkCounter++);

  sprintf(newFilename, "%s/%s",
	  Global::global.runDir,
	  newShort);

  if (filename[0] == '/') // absolute path
    sprintf(oldFilename, "%s", filename);
  else
    sprintf(oldFilename, "%s/%s", Global::global.currentDir, filename);

  if (symlink(oldFilename, newFilename) != 0)
    EXCEPTION("failed to make symlink for file");

  return strdup(newShort);
}

/**
 * replace filenames to be transfered in Arg class
 */

void
Submit :: replaceFilename(Arg * args, int nArgs,
			    vector <const char *> & toFree){
		for (int i = 0; i < nArgs; i++) {
				if (args[i].dataType == DT_FILENAME  &&
						args[i].nDim == 0) {
						const char * tmp = makeSymLink((char *)(args[i].v.p));
						toFree.push_back(tmp);

						// replace the argument;
						args[i].v.p = (void *)tmp;

						if (args[i].modeType == MODE_IN)
								stageIn.push_back(tmp);
						if (args[i].modeType == MODE_INOUT){
								stageIn.push_back(tmp);
								stageOut.push_back(tmp);
						}
						if (args[i].modeType == MODE_OUT)
								stageOut.push_back(tmp);
				}
		}
}

void
Submit :: addStageIn(const char * file) {
  stageIn.push_back(file);
}
void
Submit :: addStageOut(const char * file) {
  stageOut.push_back(file);
}

int
Submit :: submit(){
  CondorSubmit submit(module, entry, Global::global.pid, id);
  int condorJobId = submit.submit(stageIn, stageOut);
  Global::global.sessionManager.registerMap(id, condorJobId);
  return id;
}

